package com.jsu.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jsu.config.RedisCache;
import com.jsu.mapper.*;
import com.jsu.service.AgendaService;
import com.jsu.service.AgendaSubService;
import lombok.extern.slf4j.Slf4j;
import org.example.model.activity.dto.AgendaDto;
import org.example.model.activity.dto.AgendaWithFlowDTO;
import org.example.model.activity.dto.FlowWithSpeakerDTO;
import org.example.model.activity.pojo.*;

import org.example.model.common.dtos.ResponseResult;
import org.example.model.common.enums.WebHttpCodeEnum;
import org.example.model.user.pojo.Speaker;
import com.jsu.common.exception.CustomException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.sql.Date;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static org.example.model.common.enums.RedisCodeEnum.ACTIVITY;
import static org.example.model.common.enums.RedisCodeEnum.AGENDA;

@Service
@Slf4j
/*@RequiredArgsConstructor*/
public class AgendaServiceImpl implements AgendaService {
    @Autowired
    private AgendaMapper agendaMapper;
    @Autowired
    private FlowMapper flowMapper;
    @Autowired
    private FlowSpeakerMapper flowSpeakerMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AgendaSubService agendaSubService;
    /*private final UserClient userClient;*/

    @Autowired
    private SpeakerMapper speakerMapper;
    @Autowired
    private AgendaSubMapper agendaSubMapper;
    /*@Autowired(required = false)
    private SpeakerClient speakerClient;*/


    public ResponseResult getAgendaById(int id){
        String key = AGENDA.getMsg() + id;
        String cachedJson = redisCache.getCacheObject(key);
        if (cachedJson != null) {
            Agenda agenda = JSON.parseObject(cachedJson, Agenda.class);
            return ResponseResult.okResult(agenda);
        }
        Agenda agenda = agendaMapper.selectById(id);
        if(Objects.isNull(agenda)){
            return ResponseResult.errorResult(400,"查询实体不存在");
        }
        redisCache.setCacheObject(key, JSON.toJSONString(agenda));
        return ResponseResult.okResult(agenda);
    }

    @Override
    public ResponseResult getAllAgendas(Date date,Integer type,String name,Integer userId) {
        //String key = AGENDA.getMsg() + "all:";
       /* if(date==null&&type==null&&name==null){
            List<AgendaWithFlowDTO> list = redisCache.getCacheList(key);
            if (!list.isEmpty()) {
                return ResponseResult.okResult(list);
            }
        }*/

        // 获取2024年的议程列表
        LocalDate startTime = LocalDate.of(2024, 1, 1);
        LocalDate endTime = LocalDate.of(2024, 12, 31);
        LambdaQueryWrapper<Agenda> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //sql语句
        lambdaQueryWrapper.between(Agenda::getAgendaDate, startTime, endTime);
        if(date!=null){
            log.info(date.toString());
            lambdaQueryWrapper.like(Agenda::getAgendaDate,date);
        }
        if(type!=null){
            //log.info("type"+type.toString());
            lambdaQueryWrapper.eq(Agenda::getType,type);
        }
        if(name!=null){
            log.info("name"+name);
            lambdaQueryWrapper.like(Agenda::getAgendaName,name);
        }
        List<Agenda> agendaList = agendaMapper.selectList(lambdaQueryWrapper);
        if(agendaList.isEmpty()){
            return ResponseResult.errorResult(WebHttpCodeEnum.DATA_NOT_EXIST.getCode(),"数据库查询结果为空");
        }

        // 获取流程列表
        List<Flow> flowList = flowMapper.selectList(null);

        // 根据议程ID分组流程，并为每个流程添加演讲人信息
        Map<Integer, List<FlowWithSpeakerDTO>> collect = flowList.stream()
                .collect(Collectors.groupingBy(Flow::getAgendaId,
                        Collectors.mapping(flow -> getFlowWithSpeakerDTO(flow), Collectors.toList())));

        //拿到订阅的议程

        Map<Integer, AgendaSub> agendaSub = getAgendaSub(userId);

        // 转换为DTO对象
        List<AgendaWithFlowDTO> agendaWithFlowDTOList = agendaList.stream()
                .map(item -> {
                    AgendaWithFlowDTO agendaWithFlowDTO = new AgendaWithFlowDTO();
                    agendaWithFlowDTO.setFlows(collect.getOrDefault(item.getPkId(), Collections.emptyList()));
                    BeanUtils.copyProperties(item, agendaWithFlowDTO);
                    //用户该议程有进行订阅
                    if (agendaSub.containsKey(item.getPkId())){
                        agendaWithFlowDTO.setState(1);
                    }
                    else {
                        agendaWithFlowDTO.setState(0);
                    }
                    //修改类型数字为中文
                    agendaWithFlowDTO.setTypeName(getTypeInChinese(agendaWithFlowDTO.getType()));

                    return agendaWithFlowDTO;
                }).collect(Collectors.toList());

        log.info("4");
        // 缓存结果
        //redisCache.setCacheList(key, agendaWithFlowDTOList);

        return ResponseResult.okResult(agendaWithFlowDTOList);
    }
    private Map<Integer, AgendaSub> getAgendaSub(Integer userId){
        LambdaQueryWrapper<AgendaSub> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AgendaSub::getUserId,userId)
                .eq(AgendaSub::getSubscribed,1);//只查询已订阅的
        List<AgendaSub> agendaSubs = agendaSubMapper.selectList(lambdaQueryWrapper);
        //转化为map,<议程id，订阅信息>
        Map<Integer, AgendaSub> map = agendaSubs.stream().collect(Collectors.toMap(AgendaSub::getAgendaId, item -> item));

        return map;
    }
    public String getTypeInChinese(Integer type) {
        switch (type) {
            case 1:
                return "主论坛";
            case 2:
                return "平行论坛";
            case 3:
                return "科普论坛";
            case 4:
                return "掌上论剑";
            case 5:
                return "生态合作论坛";
            default:
                return "未知类型"; // 如果传入的类型数字不在范围内，返回未知类型
        }
    }
    private FlowWithSpeakerDTO getFlowWithSpeakerDTO(Flow flow) {
        List<FlowSpeaker> flowSpeakers = getFlowSpeakers(flow.getPkId());
        List<Speaker> speakers = flowSpeakers.stream()
                .map(flowSpeaker -> getSpeaker(flowSpeaker.getSpeakerId()))
                .filter(Optional::isPresent)
                .map(Optional::get)
                .collect(Collectors.toList());
        FlowWithSpeakerDTO flowWithSpeakerDTO = new FlowWithSpeakerDTO();
        flowWithSpeakerDTO.setPkId(flow.getPkId());
        flowWithSpeakerDTO.setAgendaId(flow.getAgendaId());
        flowWithSpeakerDTO.setContent(flow.getContent());//设置流程内容
        flowWithSpeakerDTO.setStartTime(flow.getStartTime());
        flowWithSpeakerDTO.setEndTime(flow.getEndTime());
        flowWithSpeakerDTO.setSpeakers(speakers);
        return flowWithSpeakerDTO;
    }

    private List<FlowSpeaker> getFlowSpeakers(Integer flowId) {
        LambdaQueryWrapper<FlowSpeaker> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FlowSpeaker::getType, 1).eq(FlowSpeaker::getFlowId, flowId);
        return flowSpeakerMapper.selectList(lambdaQueryWrapper);
    }

    private Optional<Speaker> getSpeaker(Integer speakerId) {
        return Optional.ofNullable(speakerMapper.selectById(speakerId));
    }


    @Override
    @Transactional
    public ResponseResult addOneAgenda(AgendaWithFlowDTO agendaWithFlowDTO) {
        //拿到agenda主键
        String key = AGENDA.getMsg() + agendaWithFlowDTO.getPkId();
        Agenda agenda = new Agenda();
        BeanUtils.copyProperties(agendaWithFlowDTO,agenda);
        agendaMapper.insert(agenda);//插入agenda表

        //其次拿到flow集合数据，一次存入到flow表
        /*List<FlowWithSpeakerDTO> flows = agendaWithFlowDTO.getFlows();
        if (!flows.isEmpty()){
            for (FlowWithSpeakerDTO flow : flows) {
                Flow flow1 = new Flow();
                BeanUtils.copyProperties(flow,flow1);
                flowMapper.insert(flow1);//插入该条流程
                //拿到该流程主讲人集合，再插入到flow_speaker表
                List<Speaker> speakers = flow.getSpeakers();
                for (Speaker speaker : speakers) {
                    FlowSpeaker flowSpeaker = new FlowSpeaker();
                    flowSpeaker.setSpeakerId(speaker.getPkId());//设置主讲人id
                    flowSpeaker.setType(1);//设置为议程类型
                    flowSpeaker.setFlowId(flow.getPkId());//设置流程id
                    flowSpeakerMapper.insert(flowSpeaker);//
                }
            }
        }*/
        redisCache.deleteObject(key);
        redisCache.setCacheObject(AGENDA.getMsg() + agendaWithFlowDTO.getPkId(),agendaWithFlowDTO);
        return ResponseResult.okResult("新增议程信息成功！");
    }
    @Override
    @Transactional
    public ResponseResult updateAgenda(AgendaWithFlowDTO agendaWithFlowDTO) {
        String key = AGENDA.getMsg() + agendaWithFlowDTO.getPkId();
        //首先更新agenda部分
        log.info(agendaWithFlowDTO.getPkId().toString());
        Agenda agenda = new Agenda();
        BeanUtils.copyProperties(agendaWithFlowDTO,agenda);
        agendaMapper.updateById(agenda);

        //其次更新flow部分
        for (FlowWithSpeakerDTO flow : agendaWithFlowDTO.getFlows()) {
            flowMapper.updateById(flow);
            //最后更新flow_speaker部分
            List<Speaker> speakers = flow.getSpeakers();
            LambdaQueryWrapper<FlowSpeaker> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(FlowSpeaker::getFlowId,flow.getPkId());
            flowSpeakerMapper.delete(lambdaQueryWrapper);
            //后增
            for (Speaker speaker : speakers) {
                FlowSpeaker flowSpeaker = new FlowSpeaker();
                flowSpeaker.setFlowId(flow.getPkId());
                flowSpeaker.setType(1);
                flowSpeaker.setSpeakerId(speaker.getPkId());
                flowSpeakerMapper.insert(flowSpeaker);//插入flow_speaker表
            }
        }
        redisCache.deleteObject(key);
        redisCache.setCacheObject(AGENDA.getMsg() + agendaWithFlowDTO.getPkId(),JSON.toJSONString(agendaWithFlowDTO));
        return ResponseResult.okResult("更新议程成功");
    }

    @Override
    @Transactional
    public ResponseResult delAgenda(Integer agendaId) {
        String key = AGENDA.getMsg() + agendaId;
        Agenda agenda = agendaMapper.selectById(agendaId);
        if (Objects.isNull(agenda)){
            return ResponseResult.errorResult(400,"议程不存在，删除失败");
        }
        redisCache.deleteObject(key);
        //删除agenda表的议程信息
        agendaMapper.deleteById(agendaId);
        //删除流程信息
        LambdaQueryWrapper<Flow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Flow::getAgendaId,agendaId);
        List<Flow> flowList = flowMapper.selectList(lambdaQueryWrapper);
        flowMapper.delete(lambdaQueryWrapper);
        //删除流程演讲人信息
        for (Flow flow : flowList) {
            LambdaQueryWrapper<FlowSpeaker> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            //拿到议程的对应的流程演讲集合
            lambdaQueryWrapper1.eq(FlowSpeaker::getType,1)
                    .eq(FlowSpeaker::getFlowId,flow.getPkId());
            flowSpeakerMapper.delete(lambdaQueryWrapper1);
        }
        return ResponseResult.okResult("删除议程成功");
    }

    @Override
    public ResponseResult getAllAgendasBasic() {
        List<Agenda> agendaList = agendaMapper.selectList(null);
        return ResponseResult.okResult(agendaList);
    }

    @Override
    public ResponseResult addAgendaViews(Integer agendaId) {
        Agenda agenda = agendaMapper.selectById(agendaId);
        if (Objects.isNull(agenda)){
            throw new RuntimeException("活动不存在");
        }
        agenda.setLooking(agenda.getLooking()+1);
        agendaMapper.updateById(agenda);
        String key = AGENDA.getMsg() + agendaId;
        redisCache.deleteObject(key);
        redisCache.setCacheObject(key,JSON.toJSONString(agenda));
        return ResponseResult.okResult("浏览成功");
    }


    @Override
    public ResponseResult getVideoLink(int id) {
        Agenda agenda = agendaMapper.selectById(id);
        if (Objects.isNull(agenda)){
            throw new CustomException(WebHttpCodeEnum.DATA_NOT_EXIST);
        }
        if(!StringUtils.hasLength(agenda.getVideoLink())){
            throw new CustomException(WebHttpCodeEnum.DATA_NOT_EXIST);
        }
        return ResponseResult.okResult(agenda.getVideoLink());
    }

    @Override
    public ResponseResult updateSubscriber(int agendaId,int userId,int isCancled) {
        Agenda agenda = agendaMapper.selectById(agendaId);
        if (Objects.isNull(agenda)){
            throw new CustomException(WebHttpCodeEnum.DATA_NOT_EXIST);
        }
        if (isCancled==0){
            agenda.setAgendaSubscriberNum(agenda.getAgendaSubscriberNum()+1);//订阅人数加一
            agendaMapper.updateById(agenda);
        }
        else {
            agenda.setAgendaSubscriberNum(agenda.getAgendaSubscriberNum()-1);//订阅人数加一
            agendaMapper.updateById(agenda);
        }
        //存入缓存
        redisCache.deleteObject(AGENDA.getMsg() + agendaId);
        redisCache.setCacheObject(AGENDA.getMsg() + agendaId,agenda);

        agendaSubService.updateAgendaSub(agendaId,userId,isCancled);
        return ResponseResult.okResult("更新订阅人数");
    }

    @Override
    public ResponseResult getLiveLink(int id) {
        String cacheObject = redisCache.getCacheObject(AGENDA.getMsg() + id);
        log.info("redis缓存中有数据"+cacheObject);
        //redis没有
        if(StringUtils.hasLength(cacheObject)){
            Agenda agenda = (Agenda) JSON.parse(cacheObject);
            log.info("redis缓存中有数据"+agenda.toString());
            //redis存储的没有信息
            if(!StringUtils.hasLength(agenda.getVideoLink())){
                throw new CustomException(WebHttpCodeEnum.DATA_NOT_EXIST);
            }
            else {
                return ResponseResult.okResult(agenda.getVideoLink());
            }
        }
        Agenda agenda = agendaMapper.selectById(id);
        log.info("数据库中有数据"+agenda.toString());
        if (Objects.isNull(agenda)){
            throw new CustomException(WebHttpCodeEnum.valueOf("议程会id有误！"));
        }
        String liveLink = agenda.getLiveLink();
        if (!StringUtils.hasLength(liveLink)){
            throw new CustomException(WebHttpCodeEnum.valueOf("直播链接数据有误！"));
        }
        redisCache.setCacheObject(AGENDA.getMsg() + id,JSON.toJSONString(agenda));
        return ResponseResult.okResult(liveLink);
    }

}
